using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Xml;


namespace WFTools {
    public static class XMLConfig
    {
        public static string configPath = Path.Combine(Application.dataPath, "XMLLoader/TBConfig");
        public static string codePath = Path.Combine(Application.dataPath, "XMLLoader/TBCode");//Path.Combine(Application.streamingAssetsPath, "TBCode");
        public static string dataPath = Path.Combine(Application.streamingAssetsPath, "TBData");
        
        public static char arraySplitTag = '|';
        public static char groupSplitTag = ',';
        public static string group = "c";
        public static char mapSplitTag = ':';
        public static char typeItemSplitTag = '\n';
        public static char typeFieldSplitTag = ',';

        public static string[] jumpTag = new string[] { "*", "**", "/*" };

        public static bool CheckStartsWith(string content, string[] tag)
        {
            foreach (string s in tag)
            {
                if (content.StartsWith(s)) return true;
            }
            return false;
        }

        static string[] groups;
        public static bool CheckGroup(string content)
        {
            if (string.IsNullOrEmpty(content)) return true;
            groups = content.Split(groupSplitTag);
            for (int i = 0; i < groups.Length; i++) {
                if (groups[i] == group)return true;
            }
            return false;
        }

        public static void AppendStringList(XmlNodeList xmlList, XmlNamespaceManager nsmgr, int length, List<string> strs ) {
            for (int i = 0; i < length; i++)
            {
                if (xmlList[i].Attributes.GetNamedItem("ss:Index") == null )
                {
                    if (xmlList[i].SelectSingleNode("ss:Data", nsmgr) != null)
                    {
                        strs.Add(xmlList[i].SelectSingleNode("ss:Data", nsmgr).InnerText);
                    }
                    else
                    {
                        strs.Add("");
                    }
                }
                else
                {
                    while (int.Parse(xmlList[i].Attributes["ss:Index"].Value) != strs.Count - 1)
                    {
                        strs.Add("");
                    }
                    if (xmlList[i].SelectSingleNode("ss:Data", nsmgr) != null)
                    {
                        strs[strs.Count - 1] = xmlList[i].SelectSingleNode("ss:Data", nsmgr).InnerText;
                    }
                }
            }
        }
    }

    public class EnumSheetData {
        public string EnumName, EnumSummary;
        public List<string> valusSummarys;
        public List<string> value;
        public List<string> intValue;
        public EnumSheetData(XmlNodeList rows, int index, XmlNamespaceManager nsmgr)
        {
            valusSummarys = new List<string>();
            value = new List<string>();
            intValue = new List<string>();

            var list = rows[index].SelectNodes("ss:Cell/ss:Data", nsmgr);
            EnumName = list[0].InnerText.Trim('#');
            EnumSummary = list[1].InnerText.Trim('#');

            list = rows[index + 2].SelectNodes("ss:Cell/ss:Data", nsmgr);
            for (int i = 0; i < list.Count; i++)
            {
                value.Add(list[i].InnerText);
            }

            list = rows[index + 1].SelectNodes("ss:Cell", nsmgr);
            XMLConfig.AppendStringList(list, nsmgr, value.Count, valusSummarys);

            list = rows[index + 3].SelectNodes("ss:Cell", nsmgr);
            XMLConfig.AppendStringList(list, nsmgr, value.Count, intValue);
        }
    }

    public class TypeSheetData:ISheetData
    {
         string sheetName;
        public string summary;

        List<string> groups;
        List<string> commits;
        List<string> names;
        List<string> types;

        public string SheetName => sheetName;
        public string Summary => summary;
        public List<string> Groups => groups;
        public List<string> Commits => commits;
        public List<string> Names => names;
        public List<string> Types => types;

        public TypeSheetData(XmlNodeList rows, int index, XmlNamespaceManager nsmgr)
        {
            groups = new List<string>();
            commits = new List<string>();
            types = new List<string>();
            names = new List<string>();

            var list = rows[index].SelectNodes("ss:Cell/ss:Data", nsmgr);
            sheetName = list[0].InnerText.Trim('#');
            if (list.Count>1) summary = list[1].InnerText.Trim('#');

            list = rows[index + 2].SelectNodes("ss:Cell/ss:Data", nsmgr);
            for (int i = 0; i < list.Count; i++)
            {
                Names.Add(list[i].InnerText);
            }

            list = rows[index + 1].SelectNodes("ss:Cell", nsmgr);
            XMLConfig.AppendStringList(list, nsmgr, Names.Count, Commits);

            list = rows[index + 3].SelectNodes("ss:Cell", nsmgr);
            XMLConfig.AppendStringList(list, nsmgr, Names.Count, Types);

            list = rows[index + 4].SelectNodes("ss:Cell", nsmgr);
            XMLConfig.AppendStringList(list, nsmgr, Names.Count, Groups);
        }
    }

    [Serializable]
    public class SheetData: ISheetData
    {
        string sheetName;
        string summary;
        public void SetName(string name) {
            sheetName = name;
        }
        public string SheetName => sheetName;
        public string Summary => summary;
        public List<List<string>> datas;
        public List<string> Groups => datas[3];
        public List<string> Commits => datas[0];
        public List<string> Names => datas[1];
        public List<string> Types => datas[2];
    }

    public interface ISheetData {
        public string SheetName { get; }
        public string Summary { get; }
        public List<string> Groups { get; }
        public List<string> Commits { get; }
        public List<string> Names { get; }
        public List<string> Types { get; }
    }
    public static class BinarySerializationHelper
    {
        public static byte[] SerializeToBinary(object obj)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                BinaryFormatter bf = new BinaryFormatter();
                bf.Serialize(ms, obj);
                return ms.ToArray();
            }
        }

        public static T DeserializeFromBinary<T>(byte[] data)
        {
            using (MemoryStream ms = new MemoryStream(data))
            {
                BinaryFormatter bf = new BinaryFormatter();
                return (T)bf.Deserialize(ms);
            }
        }
    }
}


